package com.monkey.service;

import com.monkey.core.ErrorCode;
import com.monkey.generator.dao.TUserMonkeyMapper;
import com.monkey.generator.dao.TUserSynthesiseMapper;
import com.monkey.generator.model.TMonkey;
import com.monkey.generator.model.TUser;
import com.monkey.generator.model.TUserExample;
import com.monkey.generator.model.TUserMonkey;
import com.monkey.generator.model.TUserMonkeyExample;
import com.monkey.generator.model.TUserSynthesise;
import com.monkey.model.monkey.Monkey;
import com.monkey.model.monkey.MonkeyData;
import com.monkey.model.monkey.MonkeySynthesise;
import com.monkey.model.synthesise.SynthesisePreviewData;
import com.monkey.model.synthesise.SynthesiseData;
import com.monkey.model.user.User;
import com.monkey.util.DateUtil;
import com.monkey.util.IDGenerator;
import com.monkey.util.WebConfig;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import static com.monkey.service.UserService.ACTION_SYNTHESISE;

import static com.monkey.service.MonkeyService.MONKEY_STATUS_NORMAL;
import static com.monkey.service.MonkeyService.MONKEY_STATUS_SYNTHESISE;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * desc: 宠物合成 auth: lpb data: 2018/2/25.
 */
@Service
@Transactional
public class SynthesiseService {
	private static Logger logger = LoggerFactory.getLogger(SynthesiseService.class);

	@Resource
	private UserService userService = null;

	@Resource
	private MonkeyService monkeyService = null;

	@Resource
	private IDGenerator idGenerator = null;

	@Resource
	private WebConfig webConfig = null;

	@Resource
	private DateUtil dateUtil = null;

	@Resource
	private TUserSynthesiseMapper userSynthesiseMapper = null;

	@Resource
	private TUserMonkeyMapper userMonkeyMapper = null;

	// 合成数据
	private SynthesisePreviewData SynthesiseData(Monkey monkey, List<Monkey> monkeys, int lucky) {
		SynthesisePreviewData result = new SynthesisePreviewData();

		if (null == monkey || null == monkeys) {
			return result;
		}

		int totalWeight = 0; // 素材宠总体重
		int totalGeneration = 0; // 素材宠总代数
		int totalGrow = 0; // 素材宠总成长数值
		int totalReproduct = 0; // 素材宠总生育数值
		int totalBonus = 0; // 素材宠总掘金数值
		for (Monkey m : monkeys) {
			totalWeight += m.getWeight();
			totalGeneration += m.getGeneration();
			totalGrow += m.getGrow();
			totalReproduct += m.getReproduct();
			totalBonus += m.getBonus();
		}

		result.setGeneration(monkey.getGeneration()); // 当前代数：继承主狗的代数
		result.setElement(monkey.getElement()); // 当前五行属性：继承主狗的五行属性
		result.setWeight(monkey.getWeight() + (totalGeneration > 0 ? (totalWeight / totalGeneration) : 0)); // 新体重：主狗体重

		// 其他四只素材狗体重总和/代数总和
		result.setReproductCount(monkey.getReproductCount()); // 新生育次数：继承主狗的生育次数

		// 成长值公式： 主狗成长值属性+0.3*其他四只素材狗成长值属性总和／(4*(2+其他四只素材狗代数／4)
		double addGrow = 0.3 * totalGrow / (4 * (2 + totalGeneration / 4.0));
		result.setGrow((int) (monkey.getGrow() + (addGrow > 1 ? addGrow : Math.ceil(addGrow))));

		// 生育值公式： 主狗生育值属性+0.3*其他四只素材狗生育值属性总和／(4*(2+其他四只素材狗代数／4)
		double addReproduct = 0.3 * totalReproduct / (4 * (2 + totalGeneration / 4.0));
		result.setReproduct((int) (monkey.getReproduct() + (addReproduct > 1 ? addReproduct : Math.ceil(addReproduct))));

		// 掘金值公式： 主狗掘金值属性+0.3*其他四只素材狗掘金值属性总和／(4*(2+其他四只素材狗代数／4)
		double addBonus = 0.3 * totalBonus / (4 * (2 + totalGeneration / 4.0));
		result.setBonus((int) (monkey.getBonus() + (addBonus > 1 ? addBonus : Math.ceil(addBonus))));

		// 神宠合成概率 = 基础概率 * 系数^代数 + 幸运值/1000
		if (monkey.getElement() != 5) {
			float basicProbability = webConfig.getFloat("synthesise.god.basic.probability"); // 基础概率
			float coefficient = webConfig.getFloat("synthesise.god.coefficient"); // 系数
			double godProbability = basicProbability * Math.pow(coefficient, monkey.getGeneration()) + lucky / 1000.0;
			result.setGodProbability((float) godProbability);
		}

		return result;
	}

	// 宠物合成预览
	public SynthesisePreviewData SynthesisePreview(User user, int monkeyId, List<Integer> monkeyIds) {
		// 主宠信息
		Monkey monkey = null;
		if (monkeyId != 0) {
			monkey = monkeyService.getMonkey(monkeyId);
			if (null == monkey) {
				return new SynthesisePreviewData();
			}
		}
		// 素材宠
		List<Monkey> monkeys = new ArrayList<>();
		for (Integer id : monkeyIds) {
			Monkey m = monkeyService.getMonkey(id);
			if (m != null) {
				monkeys.add(m);
			}
		}

		// 当前幸运值
		int lucky = user.getLucky(); // 当前幸运值

		return SynthesiseData(monkey, monkeys, lucky);
	}

	// 宠物合成
	public SynthesiseData synthesise(User user, int monkeyId, List<Integer> monkeyIds) {
		int userId = user.getId();

		// 是否激活账号
		if (!user.getEnable()) {
			return new SynthesiseData(ErrorCode.ACCOUNT_DISABLE);
		}

		int lucky = user.getLucky(); // 当前幸运值
		int price = webConfig.getInt("synthesise.gold");
		// 合成花费狗头金
		int luckyLimit = webConfig.getInt("synthesise.lucky.limit"); // 幸运值上限
		int luckyAdd = webConfig.getInt("synthesise.lucky.add"); // 未合成神宠获得的幸运值

		// 狗头金不足
		if (user.getGold().floatValue() < price) {
			return new SynthesiseData(ErrorCode.SYNTHESISE_GOLD_LESS_ERROR);
		}

		// 神宠数量
		int goldCount = 0;

		// 主宠信息
		Monkey monkey = null;
		if (monkeyId != 0) {
			monkey = monkeyService.getMonkey(monkeyId);
			if (null == monkey) {
				return new SynthesiseData(ErrorCode.SYNTHESISE_ELEMENT_ERROR);
			}
			if (userId != monkey.getUserId()) {
				return new SynthesiseData(ErrorCode.NO_OWNER_MONKEY);
			}
			if(monkey.getStatus() == MONKEY_STATUS_SYNTHESISE){
				return new SynthesiseData(ErrorCode.MONKEY_HAS_ONLY);
			}
			if (monkey.getElement() == 5) {
				goldCount += 1;
			}
		}

		// 素材宠
		List<Monkey> monkeys = new ArrayList<>();
		for (Integer id : monkeyIds) {
			Monkey m = monkeyService.getMonkey(id);
			if (m != null) {
				if (userId != m.getUserId()) {
					return new SynthesiseData(ErrorCode.NO_OWNER_MONKEY);
				}
				if (m.getStatus() != MONKEY_STATUS_NORMAL) {
					return new SynthesiseData(ErrorCode.MONKEY_HAS_ONLY);
				}
				monkeys.add(m);

				if (m.getElement() == 5) {
					goldCount += 1;
				}
			}
		}

		// 素材宠需要4只
		if (monkeys.size() != 4) {
			return new SynthesiseData(ErrorCode.SYNTHESISE_ELEMENT_ERROR);
		}

		// 主宠+4只素材宠必须满五行
		boolean exists = false;
		int lackElementCount = 0; // 缺少五行的数量
		for (int i = 0; i < 5; i++) {
			if (i == monkey.getElement()) {
				continue;
			}
			exists = false;
			for (Monkey m : monkeys) {
				if (i == m.getElement()) {
					exists = true;
					break;
				}
			}
			if (!exists) {
				lackElementCount += 1;
			}
		}
		if (goldCount < lackElementCount) {
			return new SynthesiseData(ErrorCode.SYNTHESISE_ELEMENT_ERROR);
		}
		
		
		// 原值
		int materialMonkeyId1 = monkeys.get(0).getMonId();
		int materialMonkeyId2 = monkeys.get(1).getMonId();
		int materialMonkeyId3 = monkeys.get(2).getMonId();
		int materialMonkeyId4 = monkeys.get(3).getMonId();
		int oldElement = monkey.getElement();
		int oldWeight = monkey.getWeight();
		int oldGrow = monkey.getGrow();
		int oldReproduct = monkey.getReproduct();
		int oldBonus = monkey.getBonus();
		BigDecimal oldGold = user.getGold();
		
		// 合成数据
		SynthesisePreviewData synthesiseData = SynthesiseData(monkey, monkeys, lucky);

		// 合成，生成hash
		String uuid = idGenerator.randomUUID();

		int element = synthesiseData.getElement();

		// 是否神宠
		boolean isGod = false;
		if (element != 5) {
			double r = Math.random();
			isGod = synthesiseData.getGodProbabilitySrc() > r;
			if (isGod) {
				lucky = 0;
				element = 5;
			} else {
				if (lucky < luckyLimit) {
					lucky += luckyAdd;
				}
			}
		}
		
		// 属性增量
		int weightUp = synthesiseData.getWeightSrc() - monkey.getWeight();
		int growUp = synthesiseData.getGrowSrc() - monkey.getGrow();
		int reproductUp = synthesiseData.getReproductSrc() - monkey.getReproduct();
		int bonusUp = synthesiseData.getBonusSrc() - monkey.getBonus();
		int luckyUp = isGod ? -user.getLucky() : luckyAdd;
		Date now = new Date();

		// 扣金币
		if (ErrorCode.SUCCESS != userService.deductUserGold(user, price, ACTION_SYNTHESISE)) {
			return new SynthesiseData(ErrorCode.WRITE_DB_ERROR);
		}

		// 更新幸运值
		if (ErrorCode.SUCCESS != userService.updateUserLucky(user, lucky, ACTION_SYNTHESISE)) {
			return new SynthesiseData(ErrorCode.WRITE_DB_ERROR);
		}

		// 删除副宠物
		for (Monkey m : monkeys) {
			TUserMonkey userMonkey1 = new TUserMonkey();
			userMonkey1.setStatus(MONKEY_STATUS_SYNTHESISE);
			TUserMonkeyExample example = new TUserMonkeyExample();
			example.or().andMonkeyidEqualTo(m.getId());
			example.setLimit(1);
			if (0 == userMonkeyMapper.updateByExampleSelective(userMonkey1, example)) {
				logger.info("synthesise update(delete) monkey error:{}, {}", userId, monkeyId);
				return new SynthesiseData(ErrorCode.WRITE_DB_ERROR);
			} else {
				m.setStatus(MONKEY_STATUS_SYNTHESISE);
			}
		}

		// 新的属性
		TMonkey monkey1 = new TMonkey();
		monkey.setElement(element);
		monkey1.setElement(monkey.getElement());
		monkey.setWeight(synthesiseData.getWeightSrc());
		monkey1.setWeight(monkey.getWeight());
		monkey.setGrow(synthesiseData.getGrowSrc());
		monkey1.setGrow(monkey.getGrow());
		monkey.setReproduct(synthesiseData.getReproductSrc());
		monkey1.setReproduct(monkey.getReproduct());
		monkey.setBonus(synthesiseData.getBonusSrc());
		monkey1.setBonus(monkey.getBonus());
		if (0 == monkeyService.updateMonkey(monkeyId, monkey1)) {
			logger.info("feed update monkey error:{}, {}", userId, monkeyId);
		}

		// 记录合成
		SimpleDateFormat sdf = dateUtil.getDateFormat();
		sdf.format(now);
		TUserSynthesise synthesise = new TUserSynthesise();
		synthesise.setUserid(userId);
		synthesise.setMonkeyid(monkeyId);
		synthesise.setElement(element);
		synthesise.setWeight(weightUp);
		synthesise.setGrow(growUp);
		synthesise.setReproduct(reproductUp);
		synthesise.setBonus(bonusUp);
		synthesise.setMoney(price);
		synthesise.setLucky(luckyUp);
		synthesise.setUuid(uuid);
		synthesise.setCreatetime(now);
		synthesise.setMaterialmonkeyid1(materialMonkeyId1);
		synthesise.setMaterialmonkeyid2(materialMonkeyId2);
		synthesise.setMaterialmonkeyid3(materialMonkeyId3);
		synthesise.setMaterialmonkeyid4(materialMonkeyId4);
		synthesise.setOldelement(oldElement);
		synthesise.setOldweight(oldWeight);
		synthesise.setOldgrow(oldGrow);
		synthesise.setOldreproduct(oldReproduct);
		synthesise.setOldbonus(oldBonus);
		synthesise.setOldgold(oldGold);
		if (0 == userSynthesiseMapper.insert(synthesise)) {
			logger.info("feed insert user synthesise error:{}, {}", userId, monkeyId);
		}

		// 插入记录
		int max = webConfig.getInt("synthesise.view.max");
		List<MonkeySynthesise> synthesises = monkey.getSynthesises();
		int size = synthesises.size();
		if (size >= max) {
			synthesises.remove(size - 1);
		}
		synthesises.add(0, new MonkeySynthesise(synthesise, sdf));

		logger.info("synthesise:{}, {}, e:{}, l:{}, w:{}, g:{}, r:{}, b:{}, p:{}", userId, monkeyId, element, luckyUp,
				weightUp, growUp, reproductUp, bonusUp, price);

		return new SynthesiseData(ErrorCode.SUCCESS, isGod, new MonkeyData(monkey, sdf), uuid);
	}
}
